#ifndef CLIENTCONNECTOR_H
#define CLIENTCONNECTOR_H
#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>



class ClientConnector : public QObject
{
    Q_OBJECT
public:
    explicit ClientConnector(QObject *parent = nullptr);

public slots:
    // 接受来自UI线程的信号
    void InitTcpServer();
    // 接受自己的信号
    void DealNewConnection();
    void onClientDisconnected();
    void ReadFromClient();
    // 接受来自Handler线程的信号
    void sendDataByDescriptor(const qintptr descriptor, const QByteArray responseData);
    void sendDataByUserId(const QString userId, const QByteArray responseData);
    /* 接受来自Service线程的信号 */
    // 添加套接字和UserId之间的映射，之所以说try，是因为狡猾的用户可能上了一下就下线，虚晃服务器
    void tryAddUserId(const qintptr descriptor, const QString userId);
    // Service告知某个用户主动下线，移除相关userId的映射
    void onUserIdLogout(const qintptr descriptor, const QString userId);

private:
    int PORT = 8080;

    QTcpServer* server;
    // 建立套接字描述符和套接字的映射
    QMap<qintptr, QTcpSocket*> m_descriptor2socketMap;
    // 由于套接字断开以后取不到描述符，所以需要做反向映射
    QMap<QTcpSocket*, qintptr> m_socket2descriptorMap;
    // 建立套接字描述符到UserId的映射（主要是为了同步数据库用户下线使用）
    QMap<qintptr, QString> m_descriptor2idMap;
    // 建立userId到套接字描述符的映射（主要用于根据用户id转发消息）
    QMap<QString, qintptr> m_id2descriptorMap;

signals:
    void ServerStatusChanged(bool isSuccess);
    // 发给handler线程处理用户登出
    void logoutUser(const qintptr descriptor, const QString userId);
    // 发给handler线程处理原始数据
    void handleOriginData(const qintptr descriptor, const QByteArray originData);
};

#endif // CLIENTCONNECTOR_H
